﻿using LiteBlog.Common.Components;
using LiteBlog.Common.Entities;
using LiteBlog.Common.Enums;
using LiteBlog.Components.Contracts;
using LiteBlog.Components.Enums;
using LiteBlog.Controllers.Contracts;
using LiteBlog.Controllers.Filters;
using LiteBlog.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.Script.Serialization;

namespace LiteBlog.Controllers
{
    public class SettingsController : BaseController, ISettingsController
    {
        private static readonly string StateString = "Any state";

        private IBackupComp _backupComp;
        private IDocumentComp _documentComp;
        private ISiteMapComp _sitemapComp;

        public IBackupComp BackupComponent
        {
            get
            {
                return _backupComp;
            }
        }

        public IDocumentComp DocumentComponent
        {
            get
            {
                return _documentComp;
            }
        }

        public ISiteMapComp SiteMapComponent
        {
            get
            {
                return _sitemapComp;
            }
        }

        public SettingsController(IBackupComp backupComp, 
            IDocumentComp documentComp, 
            ISiteMapComp sitemapComp, 
            ISettingsComp settingsComp, 
            ICacheComp cacheComp)
            : base(settingsComp, cacheComp)
        {
            _backupComp = backupComp;
            _documentComp = documentComp;
            _sitemapComp = sitemapComp;
        }

        [Authorize]
        [HttpGet]
        [PageExceptionFilter]
        public ActionResult Update()
        {
            var settings = SettingsComponent.Load();
            var serializer = new JavaScriptSerializer();
            var timezones = TimeZoneInfo.GetSystemTimeZones().Select(tzi => new ListOptionModel(tzi.Id, tzi.DisplayName));
            var skins = Enum.GetNames(typeof(Skin)).Select(s => new ListOptionModel(s, s));
            var postCountOptions = Enumerable.Range(1, 20).Select(i => new ListOptionModel(i.ToString(), i.ToString()));

            string registerUrl = string.Empty;
            if (string.IsNullOrEmpty(settings.AccessToken))
                registerUrl = BackupComponent.GetRegisterUrl(RedirectUrl, StateString);
            string backupUrl = Url.Action("Backup");
            string generateUrl = Url.Action("Generate");

            ViewBag.Json = serializer.Serialize(
                    new
                    {
                        Settings = settings,
                        Timezones = timezones,
                        Skins = skins,
                        PostCountOptions = postCountOptions,
                        RegisterUrl = registerUrl,
                        BackupUrl = backupUrl,
                        GenerateUrl = generateUrl
                    }
                );
            return View("Update", GetAdminLayout(), null);
        }

        [HttpPost]
        [Authorize]
        [ValidateFilter]
        [AjaxExceptionFilter]
        public ActionResult Update(Settings settings)
        {
            var oldSettings = SettingsComponent.Load();
            settings.AppKey = oldSettings.AppKey;
            settings.AppSecret = oldSettings.AppSecret;
            settings.AccessToken = oldSettings.AccessToken;
            var result = SettingsComponent.Save(settings);
            var resultModel = GetResultModel(result, null);
            return Json(resultModel);
        }

        [HttpPost]
        public ActionResult Upload()
        {
            string imageUrl = string.Empty;
            if (Request.Files != null && Request.Files.Count > 0)
            {
                HttpPostedFileBase file = this.Request.Files[0];

                if (file.ContentLength > 0)
                {
                    var document = DocumentComponent.GetNew(file.FileName);
                    file.SaveAs(document.PhysicalPath);
                    SettingsComponent.Update(SettingType.ImageUrl, document.VirtualPath);
                    imageUrl = VirtualPathUtility.ToAbsolute(document.VirtualPath);
                }
            }
            
            return Json(imageUrl);
        }


        [HttpGet]
        [PageExceptionFilter]
        public ActionResult GetAccessCode(string code, string state)
        {
            if (state == StateString)
            {
                BackupComponent.GetAndSaveAccessToken(RedirectUrl, code);
                return RedirectToAction("Update");
            }

            throw new Exception("Some cross site scripting attack, take care!!!");
        }

        [HttpGet]
        [AjaxExceptionFilter]
        public ActionResult Backup()
        {
            var result = BackupComponent.Backup();
            var resultModel = GetResultModel(result);
            return Json(resultModel, JsonRequestBehavior.AllowGet);
        }


        [HttpGet]
        [AjaxExceptionFilter]
        public ActionResult Generate()
        {
            var result = SiteMapComponent.Generate(SiteMapType.Tag);
            result = result && SiteMapComponent.Generate(SiteMapType.Category);
            result = result && SiteMapComponent.Generate(SiteMapType.Page);
            result = result && SiteMapComponent.Generate(SiteMapType.Post);

            var methodResult = result ? MethodResult.GenerateSuccess : MethodResult.GenerateFailure;
            var resultModel = GetResultModel(methodResult);
            return Json(resultModel, JsonRequestBehavior.AllowGet);
        }

        // This works only in development mode!!!
        // Use https:// for production
        // Also, register the redirect url with dropbox
        private string RedirectUrl
        {
            get
            {
                var urlHelper = new System.Web.Mvc.UrlHelper(Request.RequestContext);
                return urlHelper.Action("GetAccessCode", "Settings", null, "http");
            }
        }

        public void ResolveComponents()
        {
            
        }
    }
}
